package com.own.component.util.excel.util.read.base;

import com.own.component.util.excel.method.WorkbookMethod;
import com.own.component.util.excel.util.read.method.CellMethod;
import com.own.component.util.excel.util.read.model.MergedValueData;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Sheet;

import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

/**
 * AbstractParentExcelMethod
 *
 * @author chenxueli
 * @date 2022-10-07 17:03:00
 */
@Slf4j
public abstract class AbstractParentExcelMethod<T, CONFIG extends BaseExcelReadConfig<T>> {

    /**
     * 单元格合并的内容
     */
    private final Map<String, MergedValueData> mergedValueMap = new HashMap<>();
    /**
     * excel读取配置信息
     */
    private CONFIG currentExcelReadConfig;
    /**
     * 是否已经读过合并单元格的内容
     */
    private boolean readMergedValue = false;

    /**
     * 获取工作簿信息
     *
     * @param inputStream 文件流
     * @return 工作簿信息
     */
    protected Sheet getSheet(InputStream inputStream) {
        return getSheet(inputStream, getCurrentConfig());
    }

    /**
     * 获取工作簿信息
     *
     * @param inputStream 文件流
     * @param config      配置信息
     * @return 工作簿信息
     */
    protected Sheet getSheet(InputStream inputStream, CONFIG config) {
        if (StringUtils.isNotEmpty(config.getSheetName())) {
            return WorkbookMethod.get(inputStream).getSheet(config.getSheetName());
        }
        return WorkbookMethod.get(inputStream).getSheetAt(Math.max(config.getSheetIndex(), 0));
    }

    /**
     * 获取处理过的值信息
     *
     * @param cell 单元格
     * @return 处理过的值信息
     */
    protected String getResolveValue(Cell cell) {
        var config = getCurrentConfig();
        // 当前的处理配置信息
        var resolveValue = config.getResolveValue();
        // 获取值
        var value = CellMethod.getValue(cell, config);
        // 如果为空的情况下去查询合并单元格的信息
        if (StringUtils.isBlank(value) && config.isReadMergedValue()) {
            var key = cell.getRowIndex() + "_" + cell.getColumnIndex();
            if (mergedValueMap.containsKey(key)) {
                // 这个是是已经处理好的值了
                return mergedValueMap.get(key).getValue();
            }
        }
        // 判断是否需要处理
        return resolveValue != null ? resolveValue.apply(value) : value;
    }

    /**
     * 获取读取配置信息
     *
     * @return 读取配置信息
     */
    protected final CONFIG getCurrentConfig() {
        if (this.currentExcelReadConfig == null) {
            return getDefaultConfig();
        }
        return this.currentExcelReadConfig;
    }

    /**
     * 设置读取配置信息
     *
     * @param config 读取配置信息
     */
    protected final void setCurrentConfig(CONFIG config) {
        this.currentExcelReadConfig = config;
    }

    /**
     * 获取合并单元格的信息
     *
     * @return 合并单元格的信息
     */
    public final Map<String, MergedValueData> getMergedValueMap() {
        if (!this.readMergedValue) {
            // 获取当前的配置信息
            var config = getCurrentConfig();
            if (config.getSheet() == null) {
                return this.mergedValueMap;
            }
            // 读取信息
            this.mergedValueMap.putAll(resolveMergedValueMap(config.getSheet()));
            this.readMergedValue = true;
        }
        return this.mergedValueMap;
    }

    /**
     * 设置工作簿所有合并单元格的值
     *
     * @param sheet 工作簿
     * @return 合并单元格的值
     */
    private Map<String, MergedValueData> resolveMergedValueMap(Sheet sheet) {
        var mergedRegionList = sheet.getMergedRegions();
        var map = new HashMap<String, MergedValueData>();
        mergedRegionList.forEach(region -> {
            var firstRow = region.getFirstRow();
            var firstColumn = region.getFirstColumn();
            // 合并的单元格的值在左上角的第一个单元格
            var value = CellMethod.getValue(sheet.getRow(firstRow).getCell(firstColumn), getCurrentConfig());
            if (StringUtils.isBlank(value)) {
                return;
            }
            // 当前的处理配置信息
            var resolveValue = getCurrentConfig().getResolveValue();
            // 创建值信息
            var data = new MergedValueData(resolveValue != null ? resolveValue.apply(value) : value, region);
            // 进行赋值
            var lastRow = region.getLastRow();
            var lastColumn = region.getLastColumn();
            for (var i = firstRow; i <= lastRow; i++) {
                for (var j = firstColumn; j <= lastColumn; j++) {
                    map.put(i + "_" + j, data);
                }
            }
        });
        return map;
    }

    /**
     * 获取默认的配置信息
     *
     * @return 默认的配置信息
     */
    protected abstract CONFIG getDefaultConfig();

}
